﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;
using Microsoft.SqlServer.Server;
using System.Runtime.InteropServices;

namespace Keel.DB
{
    public class DataBaseNotConfigException : Exception
    {
        public override string Message
        {
            get
            {
                return "当前程序集使用的默认数据库尚未配置!";
            }
        }


    }
    public class Common : IDatabase
    {

        /// <summary>
        /// 当前程序集范围内使用的数据库
        /// </summary>
        public static IDatabase NowDataBase { get; set; }

        public static IDatabase GetIDatabaseByNamespace(string strnamespace, string connectstring)
        {
            IDatabase db = null;
            switch (strnamespace)
            {
                default:
                case "System.Data.SqlClient":
                    db = new SQLServer(connectstring);
                    break;
                //case "System.Data.OracleClient":
                //    dp = System.Data.OracleClient.OracleClientFactory.Instance;
                //    break;
                //case "System.Data.OleDb":
                //    dp = System.Data.OleDb.OleDbFactory.Instance;
                //    break;
                //case "System.Data.Odbc":
                //    dp = System.Data.Odbc.OdbcFactory.Instance;
                //break;
            }
            return db;

        }

        #region IDatabase 成员
        /// <summary>
        /// 获得当前数据库的提供程序
        /// </summary>
        /// <returns></returns>
        public DbProviderFactory GetProviderFactory()
        {
            if (NowDataBase == null) throw new DataBaseNotConfigException();
            return NowDataBase.GetProviderFactory();
        }
        /// <summary>
        /// 获得当前数据库的连接字符串
        /// </summary>
        public string ConnectString
        {
            get
            {
                if (NowDataBase == null) throw new DataBaseNotConfigException();
                return NowDataBase.ConnectString;
            }
            set
            {
                if (NowDataBase == null) throw new DataBaseNotConfigException();
                NowDataBase.ConnectString = value;
            }

        }


        public Type PasteType(string dbtypestring)
        {
            if (NowDataBase == null) throw new DataBaseNotConfigException();
            return NowDataBase.PasteType(dbtypestring);
        }



        public Type DBTypeToType(string dbtypestring)
        {
            return MetaType.GetMetaTypeFromDbType(PasteDBType(dbtypestring)).ClassType;
        }
       

        public DbType PasteDBType(string dbtypestring)
        {
            return NowDataBase.PasteDBType(dbtypestring);
        }

        #endregion
        public static DbType GetDBTypeByString(string dbtypestring)
        {
            return (DbType)Enum.Parse(typeof(DbType), dbtypestring, true);
        }
        /// <summary>
        /// 将一个结构转换为字符串
        /// </summary>
        /// <param name="t"></param>
        /// <returns>返回一个字符串</returns>
        public static string StructToString(object t)
        {
            int rawsize = Marshal.SizeOf(t);//得到内存大小
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);//分配内存
            Marshal.StructureToPtr(t, buffer, true);//转换结构
            byte[] rawdatas = new byte[rawsize];
            Marshal.Copy(buffer, rawdatas, 0, rawsize);//拷贝内存
            Marshal.FreeHGlobal(buffer); //释放内存
            return Encoding.Default.GetString(rawdatas);
        }
        /// <summary>
        /// 将一个字符串装转换为结构
        /// </summary>
        /// <param name="s"></param>
        /// <returns>返回一个结构</returns>
        public static object StringToStruct(string s, Type anytype)
        {
            object t = new object();
            byte[] rawdatas = Encoding.Default.GetBytes(s);
            int rawsize = Marshal.SizeOf(anytype);
            if (rawsize > rawdatas.Length)
                t = Activator.CreateInstance(anytype);
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.Copy(rawdatas, 0, buffer, rawsize);
            object retobj = Marshal.PtrToStructure(buffer, anytype);
            Marshal.FreeHGlobal(buffer);
            t = retobj;
            return t;
        }
    
  

    }
}
